package org.jw.wishlist.resolver;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Map;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jw.wishlist.entity.source.ItemSource;
import org.springframework.web.client.RestTemplate;

/**
 * @author Jiawei Zhao
 */
@Slf4j
public class JdItemSourceResolver extends ItemSourceSupports implements ItemSourceResolver {

  private static final String SOURCE_KEY = "jd";

  private final ObjectMapper objectMapper = new ObjectMapper();

  public JdItemSourceResolver(RestTemplate restTemplate) {
    super(restTemplate);
  }

  private static String getJsonString(String str) {
    int from = str.indexOf('{');
    int to = str.lastIndexOf('}') + 1;
    return str.substring(from, to);
  }

  @Override
  public ItemSource resolve(String linkCode) {

    String url = extractUrl(linkCode);
    String id = extractPropertyFromQueryString(url, "id", String.class)
        .orElseThrow(() -> new IllegalArgumentException("解析失败"));

    Document document = Optional.ofNullable(restTemplate.getForEntity(url, String.class).getBody())
        .map(Jsoup::parse)
        .orElseThrow(() -> new IllegalArgumentException("解析失败"));

    String title = Optional.ofNullable(document.select("div[id='itemName']").first())
        .map(Element::text)
        .orElseThrow(() -> new IllegalArgumentException("解析失败"));

    String pic = Optional.ofNullable(document.select("img[id='firstImg']").first())
        .map(x -> x.attr("src"))
        .map(x -> "https:" + x)
        .orElseThrow(() -> new IllegalArgumentException("解析失败"));

    @SuppressWarnings("unchecked")
    String price = document.select("script").stream()
        .filter(x -> x.childNodeSize() >= 1)
        .map(x -> x.childNode(0).toString())
        .filter(x -> x.contains("window._itemInfo"))
        .findAny()
        .map(JdItemSourceResolver::getJsonString)
        .map(x -> new StringBuilder(x)
            .deleteCharAt(x.lastIndexOf(','))
            .toString())
        .map(this::getJsonObject)
        .map(x -> (Map<String, Object>) x.get("price"))
        .map(x -> x.get("p"))
        .map(String::valueOf)
        .orElseThrow(() -> new IllegalArgumentException("解析失败"));

    return new ProductItemSourceBuilder()
        .itemId(id)
        .key(SOURCE_KEY)
        .linkCode(linkCode)
        .name(title)
        .originUrl(linkCode)
        .pictureUrl(pic)
        .price(price)
        .build();
  }

  private Map<String, Object> getJsonObject(String str) {
    try {
      return objectMapper.readValue(str, new TypeReference<>() {
      });
    } catch (JsonProcessingException e) {
      throw new IllegalArgumentException("json解析失败", e);
    }
  }
}
